package com.ifinc.common.db.jdbc;

import com.ifinc.common.db.ConnectionFactory;
import com.ifinc.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: luotao
 * Date: 12-6-11
 * Time: 17:05
 */
public abstract class AbstractTxService {
    Logger log = LoggerFactory.getLogger(getClass());

    ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();

    ThreadLocal<PreparedStatement> preparedStatementThreadLocal = new ThreadLocal<PreparedStatement>();

    ThreadLocal<ResultSet> resultSetThreadLocal = new ThreadLocal<ResultSet>();

    public void service(Map input, Map out) {
        try {
            validataInput();
            beginTx();
            doService(input, out);
            commit();
        } catch (Exception e) {
            rollback();
        } finally {
            close();
        }
    }

    private void commit() {
        Connection connection = threadLocal.get();
        try {
            if (connection != null) {
                connection.commit();
            }
        } catch (Exception e) {
            processException(e);
        }
    }

    public void validataInput() {
    }

    private void beginTx() {
        try {
            Connection connection = ConnectionFactory.getInstance().getConnection();
            if (connection != null) {
                connection.setAutoCommit(false);
                threadLocal.set(connection);
            }
        } catch (SQLException e) {
            processException(e);
        }
    }

    private void rollback() {
        Connection connection = threadLocal.get();
        try {
            if (connection != null)
                connection.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("");
        }
    }

    private void close() {
        Connection connection = threadLocal.get();
        PreparedStatement preparedStatement = preparedStatementThreadLocal.get();
        ResultSet resultSet = resultSetThreadLocal.get();
        ConnectionFactory.getInstance().closeConnection(connection, preparedStatement, resultSet);
    }

    public abstract void doService(Map input, Map out);

    protected int update(String sql, Object... values) {
        log.debug("threadId:" + Thread.currentThread().getId() + " sql : " + StringUtils.showSqlValues(sql, values));
        try {
            Connection connection = threadLocal.get();
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            if (values != null) {
                //设置sql语句参数
                for (int i = 0; i < values.length; i++) {
                    if (values[i] != null) {
                        if (values[i] instanceof java.util.Date) {
                            preparedStatement.setTimestamp(i + 1, new Timestamp(((java.util.Date) values[i]).getTime()));
                        } else {
                            preparedStatement.setObject(i + 1, values[i]);
                        }
                    } else {
                        preparedStatement.setString(i + 1, "");
                    }
                }
            }
            int update = preparedStatement.executeUpdate();
            log.debug("threadId:" + Thread.currentThread().getId() + " sql update success,update : " + update);
            return update;
        } catch (SQLException e) {
            e.printStackTrace();
            log.error(e.toString());
            throw new RuntimeException(e.getMessage() + " code = " + e.getErrorCode());
        }
    }



    public void processException(Throwable e) {
        e.printStackTrace();
        log.error(e.toString());
        throw new RuntimeException(e.toString());
    }
}
